<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    // 通过代码打印每个数据类型的原型对象，分析数据结构
    // 自定义对象（构造函数）
    // function Person() { }
    // console.log(Person.prototype);
    // console.log(Person.prototype.__proto__);
    // // Function（特殊对象）
    // console.log(Function.prototype);
    // console.log(Function.prototype.__proto__);
    // // 内置对象（Object）
    // console.log(Object.prototype);
    // ---------------------------------------------
    // 定义一个函数，然后通过原型为这个函数添加一个方法，最后调用这个方法
    // function Person() {

    // }
    // Person.prototype.name = function () {
    //     console.log('虾米');

    // };
    // var username = new Person('我的名字');
    // username.name();

    // ---------------------------------------------
    // 创建一个对象，然后通过原型为这个对象添加一个属性，最后输出这个属性的值
    // var obj = {
    // }
    // obj.__proto__.name = 'xia'
    // console.log(obj.name);
    // ---------------------------------------------
    // // 给定一个对象，如何判断一个属性是来自对象自身还是来自原型？
    // var obj = {
    //     a: 1
    // };
    // obj.__proto__.b = 2; // 在原型上添加属性
    // // 1、hasOwnProperty 方法
    // // 它检查对象自身是否具有指定的属性，而不查找原型链
    // console.log(obj.hasOwnProperty('a')); // 输出：true
    // console.log(obj.hasOwnProperty('b')); // 输出：false
    // // 2、Object.prototype.propertyIsEnumerable 方法
    // // 这个方法检查对象自身是否有指定的属性，并且这个属性是可枚举的。它不会检查原型链
    // console.log(obj.propertyIsEnumerable('a')); // 输出：true
    // console.log(obj.propertyIsEnumerable('b')); // 输出：false
    // //3、Object.getOwnPropertyDescriptor 方法
    // // 这个方法可以获取对象指定属性的描述符
    // // 如果属性不存在于对象自身，而是在原型链上，这个方法会返回 undefined
    // console.log(Object.getOwnPropertyDescriptor(obj, 'a')); // 输出：{value: 1, writable: true, enumerable: true, configurable: true}
    // console.log(Object.getOwnPropertyDescriptor(obj, 'b')); // 输出：undefined

    // ---------------------------------------------
    // 定义两个构造函数，让一个构造函数的实例通过原型链访问另一个构造函数的方法
    // function Person() {
    // }
    // function Person1() {
    // }
    // Person1.prototype.name = function () {
    //     console.log('Person1的方法');
    // }
    // var p = new Person();
    // p.__proto__ = Object.create(Person1.prototype)
    // p.name();

    // ---------------------------------------------
    // 创建一个构造函数，通过原型为其添加多个方法，然后创建该构造函数的实例并调用这些方法。
    // function Person() { }
    // Person.prototype.hobby = function () { console.log('我喜欢唱歌'); }
    // Person.prototype.man = function () { console.log('我喜欢周杰伦'); }
    // var p = new Person();
    // p.hobby();
    // p.man();

</script>

</html>